package fr.labri.harmony.analysis.jsep.results.filter;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import fr.labri.harmony.analysis.jsep.results.DBConnection;
import fr.labri.harmony.analysis.jsep.results.LoadRules;
import fr.labri.harmony.analysis.jsep.results.ProjectActivity;
import fr.labri.harmony.analysis.jsep.results.filter.CorpusMigrantsStatsSummary.DataProject;

public class CorpusStatsSummaryBigSmall extends ResultFilter {

	@Override
	public void computeResult(ResultSet rs) throws SQLException, IOException {
		Set<String> migrants = new HashSet<String>();
		Set<String> projects = new HashSet<String>();
		Map<String,DataProject> corpus = new HashMap<>();
		Map<String,Integer> usage_libs = new HashMap<String, Integer>();
		Map<String,Integer> usage_small_libs = new HashMap<String, Integer>();
		Map<String,Integer> usage_bigs_libs = new HashMap<String, Integer>();
		while (rs.next()){		
			String project = rs.getString("PROJECT");
			String source = rs.getString("NAME");
			String target = rs.getString("MIGRATION_LIB_TO");
			if(LoadRules.isTrueRule(source, target))
				migrants.add(project);
		}
		rs.first();

		ResultSet rslibs = DBConnection.fetchLatestLibsSet();
		int fixed = 0;
		int notfixed = 0;
		while (rs.next()){			
			String project = rs.getString("PROJECT");
			projects.add(project);
			if(!corpus.containsKey(project)) {
				int cloc = rs.getInt("LAST_CLOC");
				int nblibs = rs.getInt("LAST_NBLIBS");
				int nbmonths = rs.getInt("LAST_NBMONTHS");
				int commits = rs.getInt("LAST_COMMITS");
				int nbdev = rs.getInt("LAST_NBDEV");
				String libs_used = rs.getString("LAST_LIBS").replaceAll(" ", "");
				if(libs_used.equals("[]")) {
					rslibs.first();
					while(rslibs.next()) {
						String _project = rslibs.getString("PROJECT");
						if(project.equals(_project)) {
							if(rslibs.getString("LIBS_SET_AT")!=null) {
								libs_used = rslibs.getString("LIBS_SET_AT").replaceAll(" ", "");
								if(libs_used.equals("[]")==false)
									fixed++;
								else
									notfixed++;
							}
							else
								notfixed++;
							break;
						}
					}

				}
				Set<String> libs =  Utils.filterLibs(libs_used.replaceAll("\\[", "").replaceAll("\\]", "").split("\\,"));
				for(String lib : libs) {
					if(!usage_libs.containsKey(lib)) usage_libs.put(lib, 0);
					usage_libs.put(lib, usage_libs.get(lib)+1);
					if(cloc >= 15220 || commits >= 188 || nbdev >= 5) {
						if(!usage_bigs_libs.containsKey(lib)) usage_bigs_libs.put(lib, 0);
						usage_bigs_libs.put(lib, usage_bigs_libs.get(lib)+1);
					}
					if(cloc < 15220 && commits < 188 && nbdev < 5) {
						if(!usage_small_libs.containsKey(lib)) usage_small_libs.put(lib, 0);
						usage_small_libs.put(lib, usage_small_libs.get(lib)+1);
					}
						
				}
				if(nblibs==0)
					nblibs = libs.size();
				corpus.put(project, new DataProject(commits, cloc, nblibs, nbmonths, nbdev, ProjectActivity.getStart(project), ProjectActivity.getEnd(project), migrants.contains(project), libs.toString().replaceAll(" ", "")));
			}
		}
		System.out.println(fixed + " fixed projects");
		System.out.println(notfixed + " not fixed projects");
		PrintStream ps = new PrintStream(new FileOutputStream("corpus_stats.csv"));
		ps.println("PROJECT;VERSIONS;CLOC;LIBS;MONTHS;DEVS;START;END;HAS_MIGRATED;LIBS_USED");
		for(String project : corpus.keySet()) 
			ps.println(project+";"+corpus.get(project).toString());
		ps.close();
		ps = new PrintStream(System.out);
		ps.println("Nombre de projets qui utilisent des librairies : "+projects.size());

		//Usage per apis
		ps = new PrintStream(new FileOutputStream("libraries_usage_big_small.csv"));
		ps.println("LIBRARY;USAGE;USAGE_BIG;USAGE_SMALL");
		for(String library : usage_libs.keySet()){
			int big = 0, small=0;
			if(usage_bigs_libs.containsKey(library)) big = usage_bigs_libs.get(library);
			if(usage_small_libs.containsKey(library)) small = usage_small_libs.get(library);
			ps.println(library+";"+usage_libs.get(library)+";"+big+";"+small);
		}
		ps.close();
		ps = new PrintStream(System.out);

	}

	class DataProject {
		public DataProject(int commits, int cloc, int nblibs, int nbmonths, int nbdev, long start_project, long end_project, boolean hasmigrated, String libs_used) {
			super();
			this.cloc = cloc;
			this.nblibs = nblibs;
			this.nbmonths = nbmonths;
			this.nbdev = nbdev;
			this.commits = commits;
			this.start_project = start_project;
			this.end_project = end_project;
			this.hasmigrated = hasmigrated;
			this.libs_used = libs_used;
		}
		int cloc;
		int nblibs;
		int nbmonths;
		int nbdev;
		int commits;
		long start_project;
		long end_project;
		boolean hasmigrated;
		String libs_used;

		@Override
		public String toString() {
			return commits+";"+cloc+";"+nblibs+";"+nbmonths+";"+nbdev+";"+start_project+";"+end_project+";"+hasmigrated+";"+libs_used;
		}
	}
}
